package com.lvy.hczn.front.business.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lvy.hczn.front.business.service.MqttService;
import com.lvy.hczn.front.common.constant.Constants;
import com.lvy.hczn.front.common.constant.MqConstants;
import com.lvy.hczn.front.common.constant.RedisConstants;
import com.lvy.hczn.front.common.core.domain.BaseModel;
import com.lvy.hczn.front.common.core.domain.entity.SysDictData;
import com.lvy.hczn.front.common.core.redis.RedisCache;
import com.lvy.hczn.front.common.core.text.Convert;
import com.lvy.hczn.front.common.exception.UtilException;
import com.lvy.hczn.front.common.utils.DictUtils;
import com.lvy.hczn.front.system.domain.business.AccessManager;
import com.lvy.hczn.front.business.mapper.AccessManagerMapper;
import com.lvy.hczn.front.business.service.AccessManagerService;
import com.lvy.hczn.front.business.service.AccessService;
import com.lvy.hczn.front.system.domain.business.Warehouse;
import com.lvy.hczn.front.system.domain.business.WcsData;
import com.lvy.hczn.front.system.service.WarehouseService;
import com.lvy.hczn.mq.rocket.ProducerUtil;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 门禁
 *
 * @author yw
 * @date 2022-11-10 17:01:51
 **/
@Service
@Slf4j
public class AccessManagerServiceImpl extends ServiceImpl<AccessManagerMapper, AccessManager> implements AccessManagerService {

    @Autowired
    private AccessManagerMapper accessManagerMapper;

    @Autowired
    private ProducerUtil producerUtil;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private MqttService mqttService;

    @Autowired
    private RedisCache redisCache;

    //初始化设备变量
    static IntByReference device = null;

    IntByReference result_size = new IntByReference(1024);
    IntByReference result_type = new IntByReference(1024);

    IntByReference dev_num = new IntByReference(256);

    /**
     * 打开通道
     *
     * @param
     * @return boolean
     * @author yw
     * @date 2022-11-10 16:16:38
     */
    public static boolean vBarOpen() {
        device = AccessService.instance.vbar_channel_open(1, 1);
        if (device != null) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 背光控制
     *
     * @param lightState
     * @return void
     * @author yw
     * @date 2022-11-10 16:17:09
     */
    public static void vBarLight(boolean lightState) {
        byte[] buffer = new byte[64];
        int i = 0;
        if (device != null) {
            if (lightState) {
                buffer[i] = 0x55;
                buffer[++i] = (byte) 0xAA;
                buffer[++i] = 0x24;
                buffer[++i] = 0x01;
                buffer[++i] = 0x00;
                buffer[++i] = 0x01;
                buffer[++i] = (byte) 0xDB;
            } else {
                buffer[i] = 0x55;
                buffer[++i] = (byte) 0xAA;
                buffer[++i] = 0x24;
                buffer[++i] = 0x01;
                buffer[++i] = 0x00;
                buffer[++i] = 0x00;
                buffer[++i] = (byte) 0xDA;
            }
            AccessService.instance.vbar_channel_send(device, buffer, 64);
        }
    }

    /**
     * 扫码开关
     *
     * @param scanSwitch
     * @return void
     * @author yw
     * @date 2022-11-10 16:17:34
     */
    public static void controlScan(boolean scanSwitch) {
        if (device != null) {
            byte[] buffer = new byte[64];
            int i = 0;
            if (scanSwitch) {
                buffer[i] = 0x55;
                buffer[++i] = (byte) 0xAA;
                buffer[++i] = 0x05;
                buffer[++i] = 0x01;
                buffer[++i] = 0x00;
                buffer[++i] = 0x00;
                buffer[++i] = (byte) 0xFB;
            } else {
                buffer[i] = 0x55;
                buffer[++i] = (byte) 0xAA;
                buffer[++i] = 0x05;
                buffer[++i] = 0x01;
                buffer[++i] = 0x00;
                buffer[++i] = 0x01;
                buffer[++i] = (byte) 0xFA;
            }
            AccessService.instance.vbar_channel_send(device, buffer, 64);
        }
    }

    /**
     * 接收数据
     *
     * @param
     * @return java.lang.String
     * @author yw
     * @date 2022-11-10 16:17:55
     */
    public static String getResultStr() {
        String str = null;
        byte[] bufferRecv = new byte[1024];
        int recv = AccessService.instance.vbar_channel_recv(device, bufferRecv, 1024, 200);
        if (recv > 0) {
            if (bufferRecv[0] == 85 && bufferRecv[1] == -86 && bufferRecv[3] == 0) {
                //高位左移位8位 按协议低位在前 高位在后 扫码数据总长度
                int dataLen = (bufferRecv[4] & 0xff) + ((bufferRecv[5] << 8) & 0xff);
                if (dataLen > 0) {
                    byte[] receiveBuffer = new byte[dataLen];
                    System.arraycopy(bufferRecv, 6, receiveBuffer, 0, dataLen);
                    try {
                        str = new String(receiveBuffer, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        // TODO Auto-generated catch block
                        //异常记录
                        log.error("getResultStr error:{}", e);
                    }
                    log.error("getResultStr:{}", str);
                    return str;
                } else {
                    return null;
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 关闭通道
     *
     * @param
     * @return void
     * @author yw
     * @date 2022-11-10 16:18:06
     */
    public static void vBarClose() {
        if (device != null) {
            AccessService.instance.vbar_channel_close(device);
            device = null;
        }
    }

    @Deprecated
    public void scan() {
        if (vBarOpen()) {
            try {
                controlScan(true);
                vBarLight(true);
                WcsData wcsData = new WcsData();
            } catch (Exception e) {
                log.error("启动门禁异常：{}", e);
            }

            log.error("启动门禁...");

            do {
                String result = getResultStr();
                if (!StrUtil.isEmpty(result)) {
                    log.error("门禁返回：result:{}", result);
                    controlScan(false);
                    vBarLight(false);
                    try {
                        openTheDoor(result, true);
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        throw new UtilException(e);
                    } finally {
                        controlScan(true);
                        vBarLight(true);
                    }
                }
            } while (true);
        }
    }

    /**
     * 发送指令到wcs打开门禁（门禁二维码扫码获取信息放wcs那边）
     *
     * @param accessCode
     * @return void
     * @throws Exception
     * @author yw
     * @date 2022-11-10 16:18:20
     */
    @Override
    public void openTheDoor(String accessCode, boolean old) {
        if (old) {
            /*门禁程序放在WMS执行方式**/
            if (!StrUtil.isEmpty(accessCode)) {
                AccessManager accessManager = super.getOne(Wrappers.<AccessManager>lambdaQuery().eq(AccessManager::getAccessCode, accessCode).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
                Map<String, Object> map = new HashMap<>();
                if (accessManager != null) {
                    map.put(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_OPEN_DOOR_ONE, true);
                    log.error("门禁返回参数1：result:{}", JSON.toJSONString(map));
                    redisCache.set(RedisConstants.ACCESS_MANAGER_CODE, accessCode);
                } else {
                    map.put(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_OPEN_DOOR_ONE, false);
                    log.error("二维码参数不存在1：result:{}", accessCode);
                }
                mqttService.sendToMqtt(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_OPEN_DOOR, JSON.toJSONString(map));
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_OPEN_DOOR_ONE, false);
                mqttService.sendToMqtt(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_OPEN_DOOR, JSON.toJSONString(map));
            }
        } else {
            /*门禁程序放在WCS执行方式**/
            String resultCode = "code=0001";
            if (!StrUtil.isEmpty(accessCode)) {
                AccessManager accessManager = super.getOne(Wrappers.<AccessManager>lambdaQuery().eq(AccessManager::getAccessCode, accessCode).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
                Map<String, Object> map = new HashMap<>();
                if (accessManager != null) {
                    map.put("AccessManagerCodeResult", "code=0000");
                    log.error("门禁返回参数：result:{}", JSON.toJSONString(map));
                    redisCache.set(RedisConstants.ACCESS_MANAGER_CODE, accessCode);
                } else {
                    map.put("AccessManagerCodeResult", resultCode);
                    log.error("二维码参数不存在：result:{}", accessCode);
                }
                mqttService.sendToMqtt(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_ACCESS_MANAGER_CODE_RESULT, JSON.toJSONString(map));
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("AccessManagerCodeResult", resultCode);
                log.error("二维码为空");
                mqttService.sendToMqtt(com.lvy.hczn.front.business.common.Constants.TOPIC_MQTT_WMS_ACCESS_MANAGER_CODE_RESULT, JSON.toJSONString(map));
            }
        }
    }

    /**
     * 门禁置为无效，eg:多少小时内的type类型列表置为失效，
     * 如：配送单（退货配送，拒收配送）有效为五小时，五小时后，会查询type为配送单（退货配送，拒收配送）的置为失效
     *
     * @param hours
     * @param types
     * @return void
     * @author yw
     * @date 2023-07-22 18:01:48
     */
    @Override
    public void checkInvalidAccessManagerCode(String hours, String types) {
        if (NumberUtil.isInteger(hours)) {
            String[] arrayType = Convert.toStrArray(types);
            //过滤非整数参数
            List<String> newArray = Arrays.stream(arrayType).filter(NumberUtil::isInteger).collect(Collectors.toList());
            LocalDateTime localDateTime = LocalDateTime.now();
            LocalDateTime inValidTime = localDateTime.plusHours(Math.negateExact(Integer.parseInt(hours)));
            //eg：getScanTime为12点，inValidTime为12点1分，hours为1小时，inValidTime=localDateTime-hours=12点1分，则认为超过一小时，则失效
            super.remove(Wrappers.<AccessManager>lambdaQuery().isNotNull(AccessManager::getScanTime).lt(AccessManager::getScanTime, inValidTime).in(AccessManager::getType, newArray));
        }
    }

    /**
     * @Description 物理删除
     * @Param
     * @Author yw
     * @Date 2024/9/12 10:31
     * @Return
     **/
    @Override
    public int logicDelete(AccessManager accessManager) {
        if (accessManager.getCreateTime() == null || accessManager.getUpdateTime() == null) {
            throw new UtilException("参数为空");
        }
        return accessManagerMapper.logicDataDelete(accessManager);
    }

    public static void main(String[] args) {
        if (vBarOpen()) {
            //扫码开
            controlScan(true);
            vBarLight(true);
            do {
                String result = getResultStr();
                if (!StrUtil.isEmpty(result)) {
                    System.out.println(result);
                    controlScan(false);
                }
            } while (true);
        }
    }

    /**
     * 门禁扫码逻辑处理
     * 门禁扫描，扫描后，需处理业务逻辑
     * 如：根据类型只扫描一次，或者多久失效，或者永久失效，以及门禁打开后，推送到平台，告知到达仓库
     *
     * @param accessManager
     * @return void
     * @author yw
     * @date 2023-07-14 15:02:38
     */
    @Override
    public void accessManagerCode(AccessManager accessManager, boolean access) {
        List<SysDictData> list = DictUtils.getDictCache(com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE);
        if (list != null) {
            list.forEach(item -> {
                String value = item.getDictValue();
                if (accessManager.getAccessCode().startsWith(value.trim())) {
                    switch (item.getDictLabel()) {
                        case com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE_PS:
                        case com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE_XS:
                        case com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE_TH:
                        case com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE_FH:
                        case com.lvy.hczn.front.common.constant.Constants.SYS_DICT_ORDER_TYPE_YD:
                            invoiceOrRefund(accessManager, item, access);
                            break;
                        default:
                            log.error("门禁扫码信息：{}", JSONUtil.toJsonStr(accessManager));
                    }
                }
            });
        }
    }

    /**
     * 配送（运输配送/销售配送/退货配送）通知到平台，告知货物已送达仓库
     *
     * @param accessManager
     * @param sysDictData
     * @return void
     * @author yw
     * @date 2023-07-14 15:11:04
     */
    public synchronized void invoiceOrRefund(AccessManager accessManager, SysDictData sysDictData, boolean access) {
        String tag = null;
        Map<String, String> map = new HashMap<>();
        Warehouse warehouse = warehouseService.selectLocalWarehouseFront();
        if (accessManager.getType() == Constants.ACCESS_TYPE_SIX) {
            //发货配送，供应商自配，不走配送单流程
            tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_FH;
            map.put("invoiceCode", accessManager.getAccessCode());
            try {
                producerUtil.sendAsyncMsg(MqConstants.TOPIC_ARRIVE, tag, JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
            } catch (Exception e) {
                throw new UtilException(e);
            }
        } else {
            //都走门禁
            tag = MqConstants.TOPIC_ARRIVE_TAG_DELIVERY_CLERK;
            map.put("entryCode", accessManager.getAccessCode());
            map.put("repId", warehouse.getWarehouseCode());
            if (!StrUtil.isEmpty(tag)) {
                try {
                    producerUtil.sendAsyncMsg(MqConstants.TOPIC_ARRIVE, tag, JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
                } catch (Exception e) {
                    throw new UtilException(e);
                }
            }
        }

        /**入仓通知**/
        if (!access) {
            if (accessManager.getType() == Constants.ACCESS_TYPE_THREE) {
                //运输
                tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_YD;
                map.put("detailId", accessManager.getRemark());
                if (!StrUtil.isEmpty(tag)) {
                    try {
                        producerUtil.sendAsyncMsg(MqConstants.TOPIC_ARRIVE, tag, JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
                    } catch (Exception e) {
                        throw new UtilException(e);
                    }
                }
            } else {
                //所有发货配送入仓都走这里
                tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_FH_ENTRY;
                //发货单号
                map.put("invoiceCode", accessManager.getSourceCode());
                if (!StrUtil.isEmpty(tag)) {
                    try {
                        producerUtil.sendAsyncMsg(MqConstants.TOPIC_ARRIVE, tag, JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
                    } catch (Exception e) {
                        throw new UtilException(e);
                    }
                }
            }
        }

        /*if (accessManager.getType() == Constants.ACCESS_TYPE_SEVEN) {
            //销售配送
            tag = MqConstants.TOPIC_ARRIVE_TAG_DELIVERY_CLERK;
            map.put("entryCode", accessManager.getAccessCode());
        } else if (accessManager.getType() == Constants.ACCESS_TYPE_TWO || accessManager.getType() == Constants.ACCESS_TYPE_FIVE) {
            tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_PS;
            map.put("deliveryCode", accessManager.getAccessCode());
        } else if (accessManager.getType() == Constants.ACCESS_TYPE_SIX) {
            //发货配送，供应商自配，不走配送单流程
            tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_FH;
            map.put("invoiceCode", accessManager.getAccessCode());
        } else if (accessManager.getType() == Constants.ACCESS_TYPE_THREE) {
            tag = MqConstants.TOPIC_ARRIVE_TAG_GOODS_ENTRY_YD;
            map.put("detailId", accessManager.getRemark());
        }
        Warehouse warehouse = warehouseService.selectLocalWarehouseFront();
        map.put("repId", warehouse.getWarehouseCode());
        if (!StrUtil.isEmpty(tag)) {
            try {
                producerUtil.sendAsyncMsg(MqConstants.TOPIC_ARRIVE, tag, JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
            } catch (Exception e) {
                throw new UtilException(e);
            }
        }*/
    }
}
